<!DOCTYPE html>
<html lang="zh-CN">

<head>
    <meta charset="UTF-8">
<meta name="viewport"
      content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">

    <meta name="author" content="Ian Tang">


    <meta name="subtitle" content="岁月不居时节如流">


    <meta name="description" content="好记性不如烂笔头">



<title>python概述和总结 | 随笔</title>



    <link rel="icon" href="/image/The_Lion_King_32_32.png">




    <!-- stylesheets list from _config.yml -->
    
    <link rel="stylesheet" href="/css/style.css">
    



    <!-- scripts list from _config.yml -->
    
    <script src="/js/script.js"></script>
    
    <script src="/js/tocbot.min.js"></script>
    



    
    
        
    


<meta name="generator" content="Hexo 6.3.0"></head>

<body>
    <script>
        // this function is used to check current theme before page loaded.
        (() => {
            const currentTheme = window.localStorage && window.localStorage.getItem('theme') || '';
            const isDark = currentTheme === 'dark';
            const pagebody = document.getElementsByTagName('body')[0]
            if (isDark) {
                pagebody.classList.add('dark-theme');
                // mobile
                document.getElementById("mobile-toggle-theme").innerText = "· Dark"
            } else {
                pagebody.classList.remove('dark-theme');
                // mobile
                document.getElementById("mobile-toggle-theme").innerText = "· Light"
            }
        })();
    </script>

    <div class="wrapper">
        <header>
    <nav class="navbar">
        <div class="container">
            <div class="navbar-header header-logo"><a href="/">Tangkaifei&#39;s Blog</a></div>
            <div class="menu navbar-right">
                
                    <a class="menu-item" href="/archives">Posts</a>
                
                    <a class="menu-item" href="/category">Categories</a>
                
                    <a class="menu-item" href="/tag">Tags</a>
                
                    <a class="menu-item" href="/about">About</a>
                
                <input id="switch_default" type="checkbox" class="switch_default">
                <label for="switch_default" class="toggleBtn"></label>
            </div>
        </div>
    </nav>

    
    <nav class="navbar-mobile" id="nav-mobile">
        <div class="container">
            <div class="navbar-header">
                <div>
                    <a href="/">Tangkaifei&#39;s Blog</a><a id="mobile-toggle-theme">·&nbsp;Light</a>
                </div>
                <div class="menu-toggle" onclick="mobileBtn()">&#9776; Menu</div>
            </div>
            <div class="menu" id="mobile-menu">
                
                    <a class="menu-item" href="/archives">Posts</a>
                
                    <a class="menu-item" href="/category">Categories</a>
                
                    <a class="menu-item" href="/tag">Tags</a>
                
                    <a class="menu-item" href="/about">About</a>
                
            </div>
        </div>
    </nav>

</header>
<script>
    var mobileBtn = function f() {
        var toggleMenu = document.getElementsByClassName("menu-toggle")[0];
        var mobileMenu = document.getElementById("mobile-menu");
        if(toggleMenu.classList.contains("active")){
           toggleMenu.classList.remove("active")
            mobileMenu.classList.remove("active")
        }else{
            toggleMenu.classList.add("active")
            mobileMenu.classList.add("active")
        }
    }
</script>
            <div class="main">
                <div class="container">
    
    
        <div class="post-toc">
    <div class="tocbot-list">
    </div>
    <div class="tocbot-list-menu">
        <a class="tocbot-toc-expand" onclick="expand_toc()">Expand all</a>
        <a onclick="go_top()">Back to top</a>
        <a onclick="go_bottom()">Go to bottom</a>
    </div>
</div>

<script>
    var tocbot_timer;
    var DEPTH_MAX = 6; // 为 6 时展开所有
    var tocbot_default_config = {
        tocSelector: '.tocbot-list',
        contentSelector: '.post-content',
        headingSelector: 'h1, h2, h3, h4, h5',
        orderedList: false,
        scrollSmooth: true,
        onClick: extend_click,
    };

    function extend_click() {
        clearTimeout(tocbot_timer);
        tocbot_timer = setTimeout(function() {
            tocbot.refresh(obj_merge(tocbot_default_config, {
                hasInnerContainers: true
            }));
        }, 420); // 这个值是由 tocbot 源码里定义的 scrollSmoothDuration 得来的
    }

    document.ready(function() {
        tocbot.init(obj_merge(tocbot_default_config, {
            collapseDepth: 1
        }));
    });

    function expand_toc() {
        var b = document.querySelector('.tocbot-toc-expand');
        var expanded = b.getAttribute('data-expanded');
        expanded ? b.removeAttribute('data-expanded') : b.setAttribute('data-expanded', true);
        tocbot.refresh(obj_merge(tocbot_default_config, {
            collapseDepth: expanded ? 1 : DEPTH_MAX
        }));
        b.innerText = expanded ? 'Expand all' : 'Collapse all';
    }

    function go_top() {
        window.scrollTo(0, 0);
    }

    function go_bottom() {
        window.scrollTo(0, document.body.scrollHeight);
    }

    function obj_merge(target, source) {
        for (var item in source) {
            if (source.hasOwnProperty(item)) {
                target[item] = source[item];
            }
        }
        return target;
    }
</script>
    

    
    <article class="post-wrap">
        <header class="post-header">
            <h1 class="post-title">python概述和总结</h1>
            
                <div class="post-meta">
                    
                        Author: <a itemprop="author" rel="author" href="/">Ian Tang</a>
                    

                    
                        <span class="post-time">
                        Date: <a href="#">十一月 27, 2022&nbsp;&nbsp;12:46:00</a>
                        </span>
                    
                    
                        <span class="post-category">
                    Category:
                            
                                <a href="/categories/%E6%96%B9%E6%B3%95%EF%BC%9A%E6%96%B9%E6%B3%95%E8%AE%BA%EF%BC%88%E7%BB%8F%E9%AA%8C%E8%B0%88%EF%BC%89/">方法：方法论（经验谈）</a>
                            
                        </span>
                    
                </div>
            
        </header>

        <div class="post-content">
            <ul>
<li><p>python是一个解释型，交互式，无编译的面向对象语言 python缺点：</p>
<ol>
<li>运行慢，因为python是一个交互式面向对象语言，执行python语句时，每执行一句就要编译一句。c语言是编译好cpu可以执行的文件之后再运行。但是由于网络的延迟，这一缺点影响很小<br> 2.加密性。解释型语言只能发布源码，而编译型语言可以发布编译后的文件（xxx.exe）。</li>
</ol>
</li>
<li><p>python中字符串用单引号’和双引号”都可以，但不可以混用</p>
</li>
<li><p>python是一个动态语言，变量本身类型不固定</p>
</li>
<li><p>str是不变对象，而list是可变对象。对于可变对象，比如list，对list进行操作，list内部的内容是会变化的。元组(tuple)、数值型（number)、字符串(string)均为不可变对象,而字典型(dictionary)和列表型(list)的对象是可变对象</p>
</li>
</ul>
<h2 id="数字类型"><a href="#数字类型" class="headerlink" title="数字类型"></a>数字类型</h2><h3 id="整形"><a href="#整形" class="headerlink" title="整形"></a>整形</h3><p>int long</p>
<h3 id="浮点型"><a href="#浮点型" class="headerlink" title="浮点型"></a>浮点型</h3><p>float</p>
<h3 id="复数"><a href="#复数" class="headerlink" title="复数"></a>复数</h3><p>In [11]:</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">a = 1</span><br><span class="line">type(a)</span><br><span class="line">b=1.0</span><br><span class="line">type(b)</span><br><span class="line">c=1111111111111111111111111111111</span><br><span class="line">type(c)</span><br></pre></td></tr></table></figure>

<p>Out[11]:</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">int</span><br></pre></td></tr></table></figure>

<h2 id="表达式"><a href="#表达式" class="headerlink" title="表达式"></a>表达式</h2><p>不支持i++，使用i+&#x3D;1</p>
<p>In [15]:</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">a=6+8</span><br><span class="line">print (a)</span><br><span class="line">14</span><br></pre></td></tr></table></figure>

<h2 id="字符串和列表"><a href="#字符串和列表" class="headerlink" title="字符串和列表"></a>字符串和列表</h2><p>字符串就是特殊形式的列表，但是字符串的值是常量，对于字符串的更改都是更改的其副本，列表是变量，对于列表更改内容，列表地址不变。</p>
<p>字符串养成习惯用双引号来表示</p>
<p>python没有数组的概念，用列表表示，列表中可以存放任意类型的数据，同一列表可以放置多种数据</p>
<p>In [55]:</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br></pre></td><td class="code"><pre><span class="line"># 取下标操作</span><br><span class="line">str_test=&quot;hello&quot;</span><br><span class="line">list_test=[&quot;h&quot;,&quot;e&quot;,&quot;l&quot;,&quot;l&quot;,&quot;o&quot;]</span><br><span class="line">print (str_test[0])</span><br><span class="line">print (list_test[0])</span><br><span class="line"># 取1个到第3个之间的元素</span><br><span class="line">print (str_test[1:4])</span><br><span class="line">print (list_test[0:4])</span><br><span class="line"># 取第1个到5个之间的元素，每隔2个取1个</span><br><span class="line">print (str_test[0:5:2])</span><br><span class="line">print (list_test[0:5:2])</span><br><span class="line"># 取某个元素的下标</span><br><span class="line">print (str_test.index(&quot;e&quot;))</span><br><span class="line">print (list_test.index(&quot;o&quot;))</span><br><span class="line"># 逆序取得某个元素</span><br><span class="line">print (str_test[-1])</span><br><span class="line">print (list_test[-1])</span><br><span class="line"># 追加元素</span><br><span class="line">print (str_test+&quot;,world&quot;)</span><br><span class="line">print (list_test+[&quot;,&quot;,&quot;world&quot;])</span><br><span class="line"># 计算长度</span><br><span class="line">print (len(str_test))</span><br><span class="line">print (len(list_test))</span><br><span class="line"># 多次复制</span><br><span class="line">print(str_test*3)</span><br><span class="line">print(list_test*4)</span><br><span class="line"># 复制新变量</span><br><span class="line">str_new_test = str_test[:]</span><br><span class="line">list_new_test = list_test[:]</span><br><span class="line">print(str_new_test)</span><br><span class="line">print(list_new_test)</span><br><span class="line"># python中变量名有点像c中的指针</span><br><span class="line">str_new_test1 = str_new_test</span><br><span class="line">print(id(str_new_test))</span><br><span class="line">print(id(str_new_test1))</span><br><span class="line">print(id(str_test))</span><br><span class="line"></span><br><span class="line"># 列表变量可以更改元素</span><br><span class="line">list_test[1]=&quot;i&quot;</span><br><span class="line">print(list_test)</span><br><span class="line"># 列表追加</span><br><span class="line">list_test.append(&quot;world&quot;)</span><br><span class="line">print(list_test)</span><br><span class="line"></span><br><span class="line">print(list_test+[&quot;python&quot;])</span><br><span class="line"># 列表在第1位插入</span><br><span class="line">list_test[1:1]=[1234567]</span><br><span class="line">print(list_test)</span><br><span class="line"></span><br><span class="line"># 字符串的大小写转变</span><br><span class="line">str_test_upper = str_test.upper()</span><br><span class="line">print(str_test_upper)</span><br><span class="line">h</span><br><span class="line">h</span><br><span class="line">ell</span><br><span class="line">[&#x27;h&#x27;, &#x27;e&#x27;, &#x27;l&#x27;, &#x27;l&#x27;]</span><br><span class="line">hlo</span><br><span class="line">[&#x27;h&#x27;, &#x27;l&#x27;, &#x27;o&#x27;]</span><br><span class="line">1</span><br><span class="line">4</span><br><span class="line">o</span><br><span class="line">o</span><br><span class="line">hello,world</span><br><span class="line">[&#x27;h&#x27;, &#x27;e&#x27;, &#x27;l&#x27;, &#x27;l&#x27;, &#x27;o&#x27;, &#x27;,&#x27;, &#x27;world&#x27;]</span><br><span class="line">5</span><br><span class="line">5</span><br><span class="line">hellohellohello</span><br><span class="line">[&#x27;h&#x27;, &#x27;e&#x27;, &#x27;l&#x27;, &#x27;l&#x27;, &#x27;o&#x27;, &#x27;h&#x27;, &#x27;e&#x27;, &#x27;l&#x27;, &#x27;l&#x27;, &#x27;o&#x27;, &#x27;h&#x27;, &#x27;e&#x27;, &#x27;l&#x27;, &#x27;l&#x27;, &#x27;o&#x27;, &#x27;h&#x27;, &#x27;e&#x27;, &#x27;l&#x27;, &#x27;l&#x27;, &#x27;o&#x27;]</span><br><span class="line">hello</span><br><span class="line">[&#x27;h&#x27;, &#x27;e&#x27;, &#x27;l&#x27;, &#x27;l&#x27;, &#x27;o&#x27;]</span><br><span class="line">140384645081328</span><br><span class="line">140384645081328</span><br><span class="line">140384645081328</span><br><span class="line">[&#x27;h&#x27;, &#x27;i&#x27;, &#x27;l&#x27;, &#x27;l&#x27;, &#x27;o&#x27;]</span><br><span class="line">[&#x27;h&#x27;, &#x27;i&#x27;, &#x27;l&#x27;, &#x27;l&#x27;, &#x27;o&#x27;, &#x27;world&#x27;]</span><br><span class="line">[&#x27;h&#x27;, &#x27;i&#x27;, &#x27;l&#x27;, &#x27;l&#x27;, &#x27;o&#x27;, &#x27;world&#x27;, &#x27;python&#x27;]</span><br><span class="line">[&#x27;h&#x27;, 1234567, &#x27;i&#x27;, &#x27;l&#x27;, &#x27;l&#x27;, &#x27;o&#x27;, &#x27;world&#x27;]</span><br><span class="line">HELLO</span><br></pre></td></tr></table></figure>

<h2 id="列表"><a href="#列表" class="headerlink" title="列表"></a>列表</h2><p>In [*]:</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"># 几种构建列表方式</span><br><span class="line">list_test1=list(&quot;helloworld&quot;)</span><br><span class="line">list_test2=[&quot;h&quot;,&quot;e&quot;,&quot;l&quot;,&quot;l&quot;,&quot;o&quot;]</span><br><span class="line">list_test3=[x for x in range(10)]</span><br><span class="line">list_test4=map(lambda x:x ,[1,2,3,4,5])</span><br><span class="line">print(list_test4)</span><br><span class="line">print(list_test1)</span><br></pre></td></tr></table></figure>

<h2 id="lambda"><a href="#lambda" class="headerlink" title="lambda"></a><strong>lambda</strong></h2><p>构造匿名函数</p>
<p>result &#x3D; lambda x : x+1</p>
<p>等同于</p>
<p>def result(x): return x+1</p>
<h2 id="map"><a href="#map" class="headerlink" title="map"></a>map</h2><p>map(function,sequenec[,sequence, …]) –&gt;list</p>
<p>map接受两个参数，一个函数，一个可迭代的对象或者是序列，返回一个列表</p>
<h2 id="元组"><a href="#元组" class="headerlink" title="元组"></a>元组</h2><p>元组就是常量化的列表</p>
<p>tuple_test&#x3D;(1,2,3,4,5)</p>
<p>元组表达跟列表基本一致，只是元组里的元素不能修改，列表的操作（除了修改）元组也都可以操作</p>
<p>列表转为元组</p>
<p>tup_test&#x3D;tuple([1,2,3,4,5])</p>
<p><strong>什么时候用元组？当希望把一个序列作为参数传递时，不希望被修改</strong></p>
<h2 id="字典"><a href="#字典" class="headerlink" title="字典"></a>字典</h2><p>与java中map对应，字典也是一个键值对结构</p>
<p>dict_test&#x3D;{“aa”: 1, “bb”: 2 , 1:aa , 1.3:bb}</p>
<p>取值</p>
<p>dict_test[“aa”] dict_test[2]</p>
<p>dict_test[1.3]</p>
<p>新添加键值对</p>
<p>dict_test[“test”]&#x3D;”helloworld”</p>
<p>更新键值对</p>
<p>dict_test[“aa”]&#x3D;”python”</p>
<h2 id="集合"><a href="#集合" class="headerlink" title="集合"></a>集合</h2><p>集合和列表相似，但是集合不能存放相同的元素</p>
<p>set_test&#x3D;set([[1,2,3,4,5,1,2,3,4,5]])    –&gt;[1,2,3,4,5]</p>
<h2 id="异常处理"><a href="#异常处理" class="headerlink" title="异常处理"></a>异常处理</h2><p>异常处理基本同java 类似，在try点创建一个标记，当遇到异常时匹配except，抛出异常，如果没有匹配的异常，则向上传递。</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">try</span>:</span><br><span class="line">  exec1</span><br><span class="line">  <span class="keyword">try</span>:</span><br><span class="line">    exec2</span><br><span class="line">  fianlly:</span><br><span class="line">    exec3</span><br><span class="line"><span class="keyword">except</span> ErrorType:</span><br><span class="line">  catch error</span><br></pre></td></tr></table></figure>

<h2 id="函数"><a href="#函数" class="headerlink" title="函数"></a>函数</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">def func(name, age, cls=&quot;&quot;, *arg, **karg):</span><br></pre></td></tr></table></figure>

<p>函数用def定义，func是函数名，name，age是普通参数，必须按位置传入，cls是关键字参数或者默认参数，缺省可选，karg也是关键字参数，和cls关键字参数不一样的是，在函数中存在，但是不知道具体名称的关键字参数，arg是位置参数，同样是在函数中存在，但是不知道具体名称的位置参数。</p>
<p>参数的位置一定是按照（位置参数，关键字参数，*参数，**参数）的顺序来写，其中位置参数如果设定就一定要传入，如果参数定义为：</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">def</span> <span class="title function_">func</span>(<span class="params">*arg, **karg</span>):</span><br><span class="line">  state</span><br></pre></td></tr></table></figure>

<p>则表示函数可以传入任意类型和任意数量的参数</p>
<p>传参形式是有多种多样的。</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">def</span> <span class="title function_">func</span>(<span class="params">name, age=<span class="number">10</span></span>):</span><br><span class="line">  <span class="built_in">print</span> (<span class="string">&quot;name is %s, age is %d&quot;</span> %(name,age))</span><br><span class="line"><span class="comment">#调用方式</span></span><br><span class="line">func(<span class="string">&quot;hello&quot;</span>)</span><br><span class="line">func(<span class="string">&quot;hello&quot;</span>, <span class="number">20</span>)</span><br><span class="line">func(name=<span class="string">&quot;hello&quot;</span>, age=<span class="number">20</span>)</span><br><span class="line">func(age=<span class="number">20</span>, name=<span class="string">&quot;hello&quot;</span>)</span><br><span class="line"></span><br><span class="line">param_list=[<span class="string">&quot;hello&quot;</span>,<span class="number">20</span>]</span><br><span class="line">func(*param_list)</span><br><span class="line"></span><br><span class="line">param_dict=&#123;<span class="string">&quot;name&quot;</span>:<span class="string">&quot;hello&quot;</span>, <span class="string">&quot;age&quot;</span>:<span class="number">20</span>&#125;</span><br><span class="line">func(**param_dict)</span><br></pre></td></tr></table></figure>

<h2 id="迭代器"><a href="#迭代器" class="headerlink" title="迭代器"></a>迭代器</h2><p>迭代器iterator需要实现两个方法：</p>
<ol>
<li>__iter__，返回迭代器自身</li>
<li>__next__，返回迭代器下一个元素</li>
</ol>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">myiter</span>(<span class="title class_ inherited__">object</span>):</span><br><span class="line">    <span class="keyword">def</span> <span class="title function_">__init__</span>(<span class="params">self, count</span>):</span><br><span class="line">        self.count = count</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">def</span> <span class="title function_">__iter__</span>(<span class="params">self</span>):</span><br><span class="line">        <span class="keyword">return</span> self</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">def</span> <span class="title function_">__next__</span>(<span class="params">self</span>):</span><br><span class="line">        <span class="keyword">if</span> (<span class="number">0</span> &gt;= count):</span><br><span class="line">            <span class="keyword">raise</span> StopIteration()</span><br><span class="line">        <span class="keyword">else</span>:</span><br><span class="line">            self.count -= <span class="number">1</span></span><br><span class="line">            <span class="keyword">return</span> self.count</span><br><span class="line"></span><br><span class="line">myiter it = myiter(<span class="number">4</span>)</span><br><span class="line"><span class="keyword">while</span> <span class="number">1</span>:</span><br><span class="line">    e = it.__next__()</span><br><span class="line">    <span class="built_in">print</span> e</span><br></pre></td></tr></table></figure>

<h2 id="生成器"><a href="#生成器" class="headerlink" title="生成器"></a>生成器</h2><p>迭代器+协程</p>
<p>用open函数打开文件时，最好使用生成器模式。</p>
<p>创建生成器的方式</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 使用yield函数,每次执行都生成一个hello，获取它的值需要配合使用next函数或者迭代获取</span></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">first_generator</span>():</span><br><span class="line">    <span class="keyword">yield</span> <span class="string">&quot;hello&quot;</span></span><br><span class="line"></span><br><span class="line">result = first_generator()</span><br><span class="line">result.<span class="built_in">next</span>()</span><br><span class="line"><span class="comment"># 使用()获得生成器,当（）配合def使用是方法或者函数，当（）配合“,”使用是构造元组tumple，当和列表推导一起使用是生成器</span></span><br><span class="line">second_generator = (x <span class="keyword">for</span> x <span class="keyword">in</span> <span class="built_in">range</span>(<span class="number">10</span>))</span><br></pre></td></tr></table></figure>

<p>def定义的时一个普通函数，但是里面出现yield这个关键词，这就不是普通函数了，变成生成器了，有next这个成员函数（python3里变成__next__），<strong>生成器&#x3D;迭代器+协程</strong></p>
<p>yield两重魔力，第一重是迭代器有__next__函数，第二重当执行到yield时，相当于return object，但是没有并不完全一样，因为return会退出函数，而yield不会，相当于保存了运行的上下文，把函数挂起来。既然把函数挂起来，相当于该协程让出程序执行权，当__next__再次被调用，就从当前被挂起的上下文继续执行，这样可以一直循环下去，直到执行不到yield会抛出Raise StopIteration异常。</p>
<p>可以使用生成器实现cat file | grep keyword这样的Linux命令</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#!/usr/bin/python</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">with</span> <span class="built_in">open</span>(<span class="string">&quot;filepath&quot;</span>,<span class="string">&quot;r+&quot;</span>) <span class="keyword">as</span> file_obj:</span><br><span class="line">  	<span class="keyword">for</span> file <span class="keyword">in</span> file_obj:</span><br><span class="line">      	<span class="keyword">if</span> “keyword” <span class="keyword">in</span> file.strip():</span><br><span class="line">          	<span class="built_in">print</span> file</span><br><span class="line">        <span class="keyword">else</span>:</span><br><span class="line">          	<span class="keyword">pass</span></span><br></pre></td></tr></table></figure>

<p><a target="_blank" rel="noopener" href="https://segmentfault.com/a/1190000007208388">迭代器和生成器的大白话解释</a></p>
<h2 id="argv和raw-input"><a href="#argv和raw-input" class="headerlink" title="argv和raw_input"></a>argv和raw_input</h2><p>argv和raw_input都可以从命令行输入参数，不同点在于argv是从开始运行py文件时，就将输入以参数的形式在程序里使用；raw_input是在程序执行时，根据提示输入数据。</p>
<h2 id="name-x3D-x3D-main"><a href="#name-x3D-x3D-main" class="headerlink" title="__name__ &#x3D;&#x3D;__main__"></a>__name__ &#x3D;&#x3D;__main__</h2><p>__name__是内置变量，表示的是当前模块的名字。当前python文件是程序的主入口时，当前模块的__name__就是__main__，如果当前python文件不是程序的主入口，python是以模块import进来的，则__name__表示当前包的层次，是导入的文件名。</p>
<p>python的-m参数用于将一个模块或者包作为一个脚本运行，而__main__.py文件相当于是一个包的入口程序。</p>
<p><code>python xxx.py</code> 与 <code>python -m xxx.py</code> 的区别，一种是直接运行，一种是当做模块来运行。</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#!/user/bin/python</span></span><br><span class="line"><span class="comment">#coding=utf-8</span></span><br><span class="line"><span class="comment">#run.py</span></span><br><span class="line"><span class="keyword">import</span> sys</span><br><span class="line"><span class="built_in">print</span> __name__</span><br><span class="line"><span class="built_in">print</span> sys.path</span><br></pre></td></tr></table></figure>

<p>两种运行方式</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">python run.py</span><br><span class="line">__main__    #__name__的值</span><br><span class="line">[&#x27;/yh1&#x27;, &#x27;/usr/lib/python27.zip&#x27;,...]</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">python -m run.py</span><br><span class="line">run   #__name__的值</span><br><span class="line">[&#x27;&#x27;, &#x27;/usr/lib/python27.zip&#x27;, ...]</span><br><span class="line">/usr/bin/python: No module named run.py</span><br></pre></td></tr></table></figure>

<h2 id="python的简洁if语句"><a href="#python的简洁if语句" class="headerlink" title="python的简洁if语句"></a>python的简洁if语句</h2><ol>
<li>普通写法</li>
</ol>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">a, b, c = <span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span></span><br><span class="line"><span class="keyword">if</span> a &gt; b :</span><br><span class="line">    c =a </span><br><span class="line"><span class="keyword">else</span>:</span><br><span class="line">    c = b </span><br></pre></td></tr></table></figure>

<ol start="2">
<li>一行表达式，为真时放if前，也就是if前的表达式是if为true的值</li>
</ol>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">c = a <span class="keyword">if</span> a &gt; b <span class="keyword">else</span> b;</span><br></pre></td></tr></table></figure>

<ol start="3">
<li>二维列表，利用大小判断的0，1当索引</li>
</ol>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">c = [b, a][a&gt;b]</span><br></pre></td></tr></table></figure>


<h2 id="list-amp-tuple"><a href="#list-amp-tuple" class="headerlink" title="list&amp;tuple"></a>list&amp;tuple</h2><p>list是一个可变数组，tuple是一个不可变数组。（指向永不变），tuple(“a”,”b”,[“x”,”y”])，x，y可变，a，b不可变。</p>
<h2 id="dict-amp-set"><a href="#dict-amp-set" class="headerlink" title="dict&amp;set"></a>dict&amp;set</h2><p>python字典是dict函数，其他语言也有称为map，使用键-值（key-value）存储。set跟dict类似，是一组不能改变的key集合，要创建一个set，需要提供一个list作为输入集合</p>
<h2 id="range"><a href="#range" class="headerlink" title="range"></a>range</h2><p>python range()函数生成整数序列，list函数生成list，例如list(range(5))<br>###函数</p>
<ul>
<li><p>定义函数时，需要确定函数名和参数个数；</p>
</li>
<li><p>如果有必要，可以先对参数的数据类型做检查；</p>
</li>
<li><p>函数体内部可以用return随时返回函数结果；</p>
</li>
<li><p>函数执行完毕也没有return语句时，自动return None。</p>
</li>
<li><p>函数可以同时返回多个值，但其实就是一个tuple。</p>
</li>
<li><p>函数可以传递默认参数，放在可变参数后面，默认参数必须指向不变对象，不然每次调用一次默认参数的函数就会在指向对象上发生改变</p>
</li>
<li><p>函数可以定义可变参数，定义可变参数传入需是list或者tuple。或者定义函数时可变参数加上<em>。这样调用时可以输入任意数量参数，或者加上</em>的list&#x2F;tuple</p>
</li>
<li><p>关键字参数。可变参数允许你传入0个或任意个参数，这些可变参数在函数调用时自动组装为一个tuple。而关键字参数允许你传入0个或任意个含参数名的参数，这些关键字参数在函数内部自动组装为一个dict。</p>
<p> def person(name, age, **kw):<br> print(‘name:’, name, ‘age:’, age, ‘other:’, kw)</p>
</li>
</ul>
<p> 函数person除了必选参数name和age外，还接受关键字参数kw。在调用该函数时，可以只传入必选参数或者包含任意个数的关键字参数：</p>
<pre><code> person(&#39;Bob&#39;, 35, city=&#39;Beijing&#39;)
name: Bob age: 35 other: &#123;&#39;city&#39;: &#39;Beijing&#39;&#125;
</code></pre>
<ul>
<li>返回函数中内部函数可以调用外部函数的参数和局部变量，当调用外层函数输出内部函数的时候，这个参数和局部变量都保存起来了，返回的函数其实并没有被调用，只有调用返回赋值的变量的时候才被调用</li>
</ul>
<p>在Python中定义函数，可以用必选参数、默认参数、可变参数、关键字参数和命名关键字参数，这5种参数都可以组合使用。但是请注意，参数定义的顺序必须是：必选参数、默认参数、可变参数、命名关键字参数和关键字参数。</p>
<pre><code>def f1(a, b, c=0, *args, **kw):
    print(&#39;a =&#39;, a, &#39;b =&#39;, b, &#39;c =&#39;, c, &#39;args =&#39;, args, &#39;kw =&#39;, kw)

def f2(a, b, c=0, *, d, **kw):
    print(&#39;a =&#39;, a, &#39;b =&#39;, b, &#39;c =&#39;, c, &#39;d =&#39;, d, &#39;kw =&#39;, kw)
</code></pre>
<h2 id="装饰器"><a href="#装饰器" class="headerlink" title="装饰器"></a>装饰器</h2><p><a target="_blank" rel="noopener" href="https://www.cnblogs.com/cicaday/p/python-decorator.html">详解Python的装饰器</a><br>在代码运行期间动态增加功能的方式，称之为“装饰器”（Decorator），本质上，decorator就是一个返回函数的高阶函数。</p>
<h2 id="python连接数据库"><a href="#python连接数据库" class="headerlink" title="python连接数据库"></a>python连接数据库</h2><p>#数据库操作<br>采用mysql数据库</p>
<h4 id="登录数据库"><a href="#登录数据库" class="headerlink" title="登录数据库"></a>登录数据库</h4><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">mysql -uroot -p</span><br></pre></td></tr></table></figure>
<h4 id="创建数据库"><a href="#创建数据库" class="headerlink" title="创建数据库"></a>创建数据库</h4><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">create database name</span><br></pre></td></tr></table></figure>

<h4 id="显示数据库"><a href="#显示数据库" class="headerlink" title="显示数据库"></a>显示数据库</h4><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">show databases</span><br></pre></td></tr></table></figure>
<h4 id="删除数据库"><a href="#删除数据库" class="headerlink" title="删除数据库"></a>删除数据库</h4><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">drop database name</span><br></pre></td></tr></table></figure>
<h4 id="进入数据库"><a href="#进入数据库" class="headerlink" title="进入数据库"></a>进入数据库</h4><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">use databasename</span><br></pre></td></tr></table></figure>

<h2 id="sqlalchemy"><a href="#sqlalchemy" class="headerlink" title="sqlalchemy"></a>sqlalchemy</h2><p>object-relation mapping（ORM）技术，把关系数据库的表结构映射到对象上</p>
<p>安装mysql数据库、mysql-python驱动、sqlalchemy包</p>
<hr>
<ul>
<li>自增长<br>auto_increment</li>
<li>类型<br>Type</li>
<li>非空<br>not null</li>
<li>默认值<br>default ‘xx’</li>
<li>唯一<br>unique</li>
<li>指定字符集<br>charset</li>
<li>键<br>primary key</li>
<li>外键<br>增加两个表之间的联系</li>
</ul>
<hr>
<h4 id="导入sqlalchemy包"><a href="#导入sqlalchemy包" class="headerlink" title="导入sqlalchemy包"></a>导入sqlalchemy包</h4><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">from sqlalchemy import create_engine</span><br><span class="line">from sqlalchemy.ext.declarative import declarative_base</span><br><span class="line">from sqlalchemy import Column, String, Integer</span><br><span class="line">from sqlalchemy.orm import sessionmaker</span><br></pre></td></tr></table></figure>
<h4 id="与数据库连接"><a href="#与数据库连接" class="headerlink" title="与数据库连接"></a>与数据库连接</h4><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">from sqlalchemy import create_engine</span><br><span class="line">engine = create_engine(&#x27;mysql+mysqldb://root:1221@localhost:3306/pytest&#x27;)</span><br></pre></td></tr></table></figure>
<p>数据库类型+驱动：&#x2F;&#x2F;数据库账号：密码@ip：端口&#x2F;数据库名字</p>
<h4 id="创建基类"><a href="#创建基类" class="headerlink" title="创建基类"></a>创建基类</h4><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">from sqlalchemy.ext.declarative import declarative_base</span><br><span class="line"></span><br><span class="line">Base = declarative_base()</span><br></pre></td></tr></table></figure>
<h4 id="描述表结构"><a href="#描述表结构" class="headerlink" title="描述表结构"></a>描述表结构</h4><p>创建一个类User1，继承基类</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">class User1(base):</span><br><span class="line">       __tablename__:&#x27;username&#x27;</span><br><span class="line"></span><br><span class="line">       id = Colume(Integer,primary_key = True)</span><br><span class="line">       name = Colume(String(30),nullable = False,index=True)</span><br><span class="line">       password = colume(Integer)</span><br><span class="line"></span><br><span class="line">       def __repr__(self):</span><br><span class="line">              return &#x27;%s(%r)&#x27; %(self.__class__.__name__,self.username)</span><br></pre></td></tr></table></figure>

<p>__tabelename__指定表的名字，除了String、Integer类型还有Text，Boolean，DateTime等。nullable&#x3D;False 代表这一列不可以为空，index&#x3D;True 表示在该列创建索引。定义 <strong>repr</strong> 是为了方便调试，你可以不定义，也可以定义的更详细一些</p>
<h4 id="创建实例（建立表）"><a href="#创建实例（建立表）" class="headerlink" title="创建实例（建立表）"></a>创建实例（建立表）</h4><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Base.metadata.create_all(engine) </span><br></pre></td></tr></table></figure>



<h4 id="建立会话"><a href="#建立会话" class="headerlink" title="建立会话"></a>建立会话</h4><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">om sqlalchemy.orm import sessionmaker</span><br><span class="line"></span><br><span class="line">Session = sessionmaker(bind=engine)</span><br><span class="line">session = Session()</span><br></pre></td></tr></table></figure>
<p>可以把 sessionmaker 想象成一个手机，engine 当做 MySQL 的号码，拨通这个“号码”我们就创建了一个 Session 类，下面就可以通过这个类的实例与 MySQL 愉快的交谈了！</p>
<h2 id="简单-CURD"><a href="#简单-CURD" class="headerlink" title="简单 CURD"></a>简单 CURD</h2><h4 id="Create"><a href="#Create" class="headerlink" title="Create"></a>Create</h4><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">ssion.add_all([User1(name = &#x27;ed&#x27;,password = &#x27;1111111&#x27;),</span><br><span class="line">User1(name = &#x27;ad&#x27;,password = &#x27;1111112&#x27;),</span><br><span class="line">])</span><br><span class="line">session.commit()</span><br><span class="line"></span><br></pre></td></tr></table></figure>
<h4 id="Retrieve"><a href="#Retrieve" class="headerlink" title="Retrieve"></a>Retrieve</h4><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">for instance in session.query(tang).order_by(tang.name):</span><br><span class="line">            print(instance.name, instance.age)</span><br><span class="line">for name, fullname in session.query(tang.name, tang.age):</span><br><span class="line">            print(name, fullname)</span><br><span class="line">print(session.query(tang).get(5)) </span><br><span class="line">for t1, in session.query(tang.name).filter(tang.age == 24):</span><br><span class="line">            print t1</span><br></pre></td></tr></table></figure>
<p>session.query(class).get(index)<br>或者<br>session.query(class.colume)<br>session.query(class).all()<br>session.query(class.colume).filter(条件)</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#相等</span></span><br><span class="line">query.<span class="built_in">filter</span>(User.name == <span class="string">&#x27;ed&#x27;</span>)</span><br><span class="line"><span class="comment">#不相等</span></span><br><span class="line">query.<span class="built_in">filter</span>(User.name != <span class="string">&#x27;ed&#x27;</span>)</span><br><span class="line"><span class="comment">#like</span></span><br><span class="line">query.<span class="built_in">filter</span>(User.name.like(<span class="string">&#x27;%ed%&#x27;</span>))</span><br><span class="line"><span class="comment">#in</span></span><br><span class="line">query.<span class="built_in">filter</span>(User.name.in_([<span class="string">&#x27;ed&#x27;</span>, <span class="string">&#x27;wendy&#x27;</span>, <span class="string">&#x27;jack&#x27;</span>]))</span><br><span class="line">query.<span class="built_in">filter</span>(User.name.in_(</span><br><span class="line">    session.query(User.name).<span class="built_in">filter</span>(User.name.like(<span class="string">&#x27;%ed%&#x27;</span>))</span><br><span class="line">))</span><br><span class="line"><span class="comment">#not in</span></span><br><span class="line">query.<span class="built_in">filter</span>(~User.name.in_([<span class="string">&#x27;ed&#x27;</span>, <span class="string">&#x27;wendy&#x27;</span>, <span class="string">&#x27;jack&#x27;</span>]))</span><br><span class="line"><span class="comment">#IS NULL</span></span><br><span class="line">query.<span class="built_in">filter</span>(User.name == <span class="literal">None</span>)</span><br><span class="line">query.<span class="built_in">filter</span>(User.name.is_(<span class="literal">None</span>))</span><br><span class="line"><span class="comment">#IS NOT NUKK</span></span><br><span class="line">query.<span class="built_in">filter</span>(User.name != <span class="literal">None</span>)</span><br><span class="line">query.<span class="built_in">filter</span>(User.name.isnot(<span class="literal">None</span>))</span><br><span class="line"><span class="comment">#And</span></span><br><span class="line"><span class="keyword">from</span> sqlalchemy <span class="keyword">import</span> and_</span><br><span class="line">query.<span class="built_in">filter</span>(and_(User.name == <span class="string">&#x27;ed&#x27;</span>, User.fullname == <span class="string">&#x27;Ed Jones&#x27;</span>))</span><br><span class="line">query.<span class="built_in">filter</span>(User.name == <span class="string">&#x27;ed&#x27;</span>, User.fullname == <span class="string">&#x27;Ed Jones&#x27;</span>)</span><br><span class="line">query.<span class="built_in">filter</span>(User.name == <span class="string">&#x27;ed&#x27;</span>).<span class="built_in">filter</span>(User.fullname == <span class="string">&#x27;Ed Jones&#x27;</span>)</span><br><span class="line"><span class="comment">#OR</span></span><br><span class="line"><span class="keyword">from</span> sqlalchemy <span class="keyword">import</span> or_</span><br><span class="line">query.<span class="built_in">filter</span>(or_(User.name == <span class="string">&#x27;ed&#x27;</span>, User.name == <span class="string">&#x27;wendy&#x27;</span>))</span><br><span class="line"><span class="comment">#Match</span></span><br><span class="line">query.<span class="built_in">filter</span>(User.name.<span class="keyword">match</span>(<span class="string">&#x27;wendy&#x27;</span>))</span><br></pre></td></tr></table></figure>
<h4 id="update"><a href="#update" class="headerlink" title="update"></a>update</h4><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">a = session.query(User1).get(1)</span><br><span class="line">a.password=88888</span><br><span class="line">session.add(a)</span><br><span class="line">session.commit()</span><br></pre></td></tr></table></figure>
<h4 id="delete"><a href="#delete" class="headerlink" title="delete"></a>delete</h4><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">a = session.query(User1).get(1)</span><br><span class="line">session.delete(a)</span><br><span class="line">session.commit()</span><br></pre></td></tr></table></figure>
<h2 id="python处理日志"><a href="#python处理日志" class="headerlink" title="python处理日志"></a>python处理日志</h2><h5 id="日志相关概念"><a href="#日志相关概念" class="headerlink" title="日志相关概念"></a>日志相关概念</h5><p>日志是一种可以追踪某些软件运行时所发生事件的方法。软件开发人员可以向他们的代码中调用日志记录相关的方法来表<br>明发生了某些事情。一个事件可以用一个可包含可选变量数据的消息来描述。此外，事件也有重要性的概念，这个重要性<br>也可以被称为严重性级别（level）。</p>
<h5 id="日志的作用"><a href="#日志的作用" class="headerlink" title="日志的作用"></a>日志的作用</h5><p>通过log的分析，可以方便用户了解系统或软件、应用的运行情况；如果你的应用log足够丰富，也可以分析以往用户的操<br>作行为、类型喜好、地域分布或其他更多信息；如果一个应用的log同时也分了多个级别，那么可以很轻易地分析得到该<br>应用的健康状况，及时发现问题并快速定位、解决问题，补救损失。<br>简单来讲就是，我们通过记录和分析日志可以了解一个系统或软件程序运行情况是否正常，也可以在应用程序出现故障时<br>快速定位问题。比如，做运维的同学，在接收到报警或各种问题反馈后，进行问题排查时通常都会先去看各种日志，大部<br>分问题都可以在日志中找到答案。再比如，做开发的同学，可以通过IDE控制台上输出的各种日志进行程序调试。对于运<br>维老司机或者有经验的开发人员，可以快速的通过日志定位到问题的根源。可见，日志的重要性不可小觑。日志的作用可<br>以简单总结为以下3点：<br>•程序调试<br>•了解软件程序运行情况，是否正常<br>•软件程序运行故障分析与问题定位<br>如果应用的日志信息足够详细和丰富，还可以用来做用户行为分析，如：分析用户的操作行为、类型洗好、地域分布以及<br>其它更多的信息，由此可以实现改进业务、提高商业利益。</p>
<h5 id="日志的等级"><a href="#日志的等级" class="headerlink" title="日志的等级"></a>日志的等级</h5><p>我们先来思考下下面的两个问题：<br>•作为开发人员，在开发一个应用程序时需要什么日志信息？在应用程序正式上线后需要什么日志信息？<br>•作为应用运维人员，在部署开发环境时需要什么日志信息？在部署生产环境时需要什么日志信息？<br>在软件开发阶段或部署开发环境时，为了尽可能详细的查看应用程序的运行状态来保证上线后的稳定性，我们可能需要把<br>该应用程序所有的运行日志全部记录下来进行分析，这是非常耗费机器性能的。当应用程序正式发布或在生产环境部署应<br>用程序时，我们通常只需要记录应用程序的异常信息、错误信息等，这样既可以减小服务器的I&#x2F;O压力，也可以避免我们<br>在排查故障时被淹没在日志的海洋里。那么，怎样才能在不改动应用程序代码的情况下实现在不同的环境记录不同详细程<br>度的日志呢？这就是日志等级的作用了，我们通过配置文件指定我们需要的日志等级就可以了。<br>不同的应用程序所定义的日志等级可能会有所差别，分的详细点的会包含以下几个等级：<br>• DEBUG<br>• INFO<br>•NOTICE<br>•WARNING<br>•ERROR<br>•CRITICAL<br>•ALERT<br>•EMERGENCY</p>
<h5 id="日志字段信息与日志格式"><a href="#日志字段信息与日志格式" class="headerlink" title="日志字段信息与日志格式"></a>日志字段信息与日志格式</h5><p>本节开始问题提到过，一条日志信息对应的是一个事件的发生，而一个事件通常需要包括以下几个内容：<br>•事件发生时间<br>•事件发生位置<br>•事件的严重程度–日志级别<br>•事件内容<br>上面这些都是一条日志记录中可能包含的字段信息，当然还可以包括一些其他信息，如进程ID、进程名称、线程ID、线程<br>名称等。日志格式就是用来定义一条日志记录中包含那些字段的，且日志格式通常都是可以自定义的。<br>说明：<br>输出一条日志时，日志内容和日志级别是需要开发人员明确指定的。对于而其它字段信息，只需要是否显示在日志中就可<br>以了。</p>
<h5 id="日志功能的实现"><a href="#日志功能的实现" class="headerlink" title="日志功能的实现"></a>日志功能的实现</h5><p>几乎所有开发语言都会内置日志相关功能，或者会有比较优秀的第三方库来提供日志操作功能，比如：log4j，log4php<br>等。它们功能强大、使用简单。Python自身也提供了一个用于记录日志的标准库模块–logging。</p>
<h4 id="logging模块简介"><a href="#logging模块简介" class="headerlink" title="logging模块简介"></a>logging模块简介</h4><p>logging模块定义的函数和类为应用程序和库的开发实现了一个灵活的事件日志系统。logging模块是Python的一个标准<br>库模块，由标准库模块提供日志记录API的关键好处是所有Python模块都可以使用这个日志记录功能。所以，你的应用日<br>志可以将你自己的日志信息与来自第三方模块的信息整合起来。</p>
<h5 id="logging模块的日志级别"><a href="#logging模块的日志级别" class="headerlink" title="logging模块的日志级别"></a>logging模块的日志级别</h5><p>logging模块默认定义了以下几个日志等级，它允许开发人员自定义其他日志级别，但是这是不被推荐的，尤其是在开发<br>供别人使用的库时，因为这会导致日志级别的混乱。<br>日志等级（level）<br>描述<br>Alt text<br>开发应用程序或部署开发环境时，可以使用DEBUG或INFO级别的日志获取尽可能详细的日志信息来进行开发或部署调<br>试；应用上线或部署生产环境时，应该使用WARNING或ERROR或CRITICAL级别的日志来降低机器的I&#x2F;O压力和提高获取<br>错误日志信息的效率。日志级别的指定通常都是在应用程序的配置文件中进行指定的。<br>说明：<br>•上面列表中的日志等级是从上到下依次升高的，即：DEBUG &lt; INFO &lt; WARNING &lt; ERROR &lt; CRITICAL，而日志的<br>信息量是依次减少的；<br>•当为某个应用程序指定一个日志级别后，应用程序会记录所有日志级别大于或等于指定日志级别的日志信息，而不是仅<br>仅记录指定级别的日志信息，nginx、php等应用程序以及这里要提高的python的logging模块都是这样的。同样，<br>logging模块也可以指定日志记录器的日志级别，只有级别大于或等于该指定日志级别的日志记录才会被输出，小于该等<br>级的日志记录将会被丢弃。</p>
<h5 id="logging模块的使用方式介绍"><a href="#logging模块的使用方式介绍" class="headerlink" title="logging模块的使用方式介绍"></a>logging模块的使用方式介绍</h5><p>logging模块提供了两种记录日志的方式：<br>•第一种方式是使用logging提供的模块级别的函数<br>•第二种方式是使用Logging日志系统的四大组件<br>其实，logging所提供的模块级别的日志记录函数也是对logging日志系统相关类的封装而已。<br>logging模块定义的模块级别的常用函数<br>Alt text<br>其中logging.basicConfig(** kwargs)函数用于指定“要记录的日志级别”、“日志格式”、“日志输出位置”、“日志文件的打<br>开模式”等信息，其他几个都是用于记录各个级别日志的函数。<br>logging模块的四大组件<br>Alt text<br>说明： logging模块提供的模块级别的那些函数实际上也是通过这几个组件的相关实现类来记录日志的，只是在创建这些<br>类的实例时设置了一些默认值。</p>
<h5 id="使用logging提供的模块级别的函数记录日志"><a href="#使用logging提供的模块级别的函数记录日志" class="headerlink" title="使用logging提供的模块级别的函数记录日志"></a>使用logging提供的模块级别的函数记录日志</h5><p>回顾下前面提到的几个重要信息：<br>•可以通过logging模块定义的模块级别的方法去完成简单的日志记录<br>•只有级别大于或等于日志记录器指定级别的日志记录才会被输出，小于该级别的日志记录将会被丢弃。</p>
<h5 id="最简单的日志输出"><a href="#最简单的日志输出" class="headerlink" title="最简单的日志输出"></a>最简单的日志输出</h5><p>先来试着分别输出一条不同日志级别的日志记录：</p>
<p>import logging<br>logging.debug(“This is a debug log.”)</p>
<p>logging.info(“This is a info log.”)<br>logging.warning(“This is a warning log.”)<br>logging.error(“This is a error log.”)<br>logging.critical(“This is a critical log.”)<br>输出结果：<br>WARNING:root:This is a warning log.<br>ERROR:root:This is a error log.<br>CRITICAL:root:This is a critical log.</p>
<h5 id="那么问题来了"><a href="#那么问题来了" class="headerlink" title="那么问题来了"></a>那么问题来了</h5><p>问题1：为什么前面两条日志没有被打印出来？<br>这是因为logging模块提供的日志记录函数所使用的日志器设置的日志级别是WARNING，因此只有WARNING级别的日志<br>记录以及大于它的ERROR和CRITICAL级别的日志记录被输出了，而小于它的DEBUG和INFO级别的日志记录被丢弃了。<br>问题2：打印出来的日志信息中各字段表示什么意思？为什么会这样输出？<br>上面输出结果中每行日志记录的各个字段含义分别是：<br>日志级别:日志器名称:日志内容<br>之所以会这样输出，是因为logging模块提供的日志记录函数所使用的日志器设置的日志格式默认是BASIC_FORMAT，其<br>值为：</p>
<p>“%(levelname)s:%(name)s:%(message)s”<br>问题3：如果将日志记录输出到文件中，而不是打印到控制台？<br>因为在logging模块提供的日志记录函数所使用的日志器设置的处理器所指定的日志输出位置默认为:<br>sys.stderr<br>问题4：我是怎么知道这些的？<br>查看这些日志记录函数的实现代码，可以发现：当我们没有提供任何配置信息的时候，这些函数都会去调用<br>logging.basicConfig(** kwargs)方法，且不会向该方法传递任何参数。继续查看basicConfig()方法的代码就可以找到上<br>面这些问题的答案了。<br>问题5：怎么修改这些默认设置呢？<br>其实很简单，在我们调用上面这些日志记录函数之前，手动调用一下basicConfig()方法，把我们想设置的内容以参数的<br>形式传递进去就可以了。</p>
<h5 id="logging-basicConfig-函数说明"><a href="#logging-basicConfig-函数说明" class="headerlink" title="logging.basicConfig()函数说明"></a>logging.basicConfig()函数说明</h5><p>该方法用于为logging日志系统做一些基本配置，方法定义如下：<br>logging.basicConfig(** kwargs)</p>
<p>该函数可接收的关键字参数如下：<br>Alt text</p>
<h5 id="logging模块定义的格式字符串字段"><a href="#logging模块定义的格式字符串字段" class="headerlink" title="logging模块定义的格式字符串字段"></a>logging模块定义的格式字符串字段</h5><p>我们来列举一下logging模块中定义好的可以用于format格式字符串中字段有哪些：<br>Alt text</p>
<h5 id="经过配置的日志输出"><a href="#经过配置的日志输出" class="headerlink" title="经过配置的日志输出"></a>经过配置的日志输出</h5><p>先简单配置下日志器的日志级别</p>
<p>logging.basicConfig(level&#x3D;logging.DEBUG)<br>logging.debug(“This is a debug log.”)<br>logging.info(“This is a info log.”)<br>logging.warning(“This is a warning log.”)<br>logging.error(“This is a error log.”)<br>logging.critical(“This is a critical log.”)<br>输出结果：<br>DEBUG:root:This is a debug log.<br>INFO:root:This is a info log.<br>WARNING:root:This is a warning log.<br>ERROR:root:This is a error log.<br>CRITICAL:root:This is a critical log.<br>所有等级的日志信息都被输出了，说明配置生效了。<br>在配置日志器日志级别的基础上，在配置下日志输出目标文件和日志格式</p>
<p>LOG_FORMAT &#x3D; “%(asctime)s ‐ %(levelname)s ‐ %(message)s”<br>logging.basicConfig(filename&#x3D;’my.log’, level&#x3D;logging.DEBUG, format&#x3D;LOG_FORMAT)<br>logging.debug(“This is a debug log.”)<br>logging.info(“This is a info log.”)<br>logging.warning(“This is a warning log.”)<br>logging.error(“This is a error log.”)<br>logging.critical(“This is a critical log.”)<br>此时会发现控制台中已经没有输出日志内容了，但是在python代码文件的相同目录下会生成一个名为’my.log’的日志文<br>件，该文件中的内容为：<br>2017‐05‐08<br>2017‐05‐08<br>2017‐05‐08<br>2017‐05‐08<br>2017‐05‐08</p>
<p>14:29:53,783<br>14:29:53,784<br>14:29:53,784<br>14:29:53,784<br>14:29:53,784</p>
<p>‐<br>‐<br>‐<br>‐<br>‐</p>
<p>DEBUG ‐ This is a debug log.<br>INFO ‐ This is a info log.<br>WARNING ‐ This is a warning log.<br>ERROR ‐ This is a error log.<br>CRITICAL ‐ This is a critical log.</p>
<p>在上面的基础上，我们再来设置下日期&#x2F;时间格式</p>
<p>LOG_FORMAT &#x3D; “%(asctime)s ‐ %(levelname)s ‐ %(message)s”<br>DATE_FORMAT &#x3D; “%m&#x2F;%d&#x2F;%Y %H:%M:%S %p”<br>logging.basicConfig(filename&#x3D;’my.log’, level&#x3D;logging.DEBUG, format&#x3D;LOG_FORMAT,<br>datefmt&#x3D;DATE_FORMAT)<br>logging.debug(“This is a debug log.”)<br>logging.info(“This is a info log.”)<br>logging.warning(“This is a warning log.”)<br>logging.error(“This is a error log.”)<br>logging.critical(“This is a critical log.”)</p>
<ol start="6">
<li>其他说明<br>几个要说明的内容：<br>•logging.basicConfig()函数是一个一次性的简单配置工具使，也就是说只有在第一次调用该函数时会起作用，后续再次<br>调用该函数时完全不会产生任何操作的，多次调用的设置并不是累加操作。<br>•日志器（Logger）是有层级关系的，上面调用的logging模块级别的函数所使用的日志器是RootLogger类的实例，其<br>名称为’root’，它是处于日志器层级关系最顶层的日志器，且该实例是以单例模式存在的。<br>•如果要记录的日志中包含变量数据，可使用一个格式字符串作为这个事件的描述消息（logging.debug、logging.info<br>等函数的第一个参数），然后将变量数据作为第二个参数<em>args的值进行传递，如:logging.warning(‘%s is %d years<br>old.’, ‘Tom’, 10)，输出内容为WARNING:root:Tom is 10 years old.<br>•logging.debug(), logging.info()等方法的定义中，除了msg和args参数外，还有一个</em>* kwargs参数。它们支持3个关<br>键字参数: exc_info, stack_info, extra，下面对这几个关键字参数作个说明。<br>关于exc_info, stack_info, extra关键词参数的说明:<br>•exc_info： 其值为布尔值，如果该参数的值设置为True，则会将异常异常信息添加到日志消息中。如果没有异常信息<br>则添加None到日志信息中。<br>•stack_info： 其值也为布尔值，默认值为False。如果该参数的值设置为True，栈信息将会被添加到日志信息中。<br>•extra： 这是一个字典（dict）参数，它可以用来自定义消息格式中所包含的字段，但是它的key不能与logging模块定<br>义的字段冲突。<br>一个例子：<br>在日志消息中添加exc_info和stack_info信息，并添加两个自定义的字端 ip和user<br>LOG_FORMAT &#x3D; “%(asctime)s ‐ %(levelname)s ‐ %(user)s[%(ip)s] ‐ %(message)s”<br>DATE_FORMAT &#x3D; “%m&#x2F;%d&#x2F;%Y %H:%M:%S %p”<br>logging.basicConfig(format&#x3D;LOG_FORMAT, datefmt&#x3D;DATE_FORMAT)<br>logging.warning(“Some one delete the log file.”, exc_info&#x3D;True, stack_info&#x3D;True, extra&#x3D;<br>{‘user’: ‘Tom’, ‘ip’:’47.98.53.222’})<br>输出结果：<br>05&#x2F;08&#x2F;2017 16:35:00 PM ‐ WARNING ‐ Tom[47.98.53.222] ‐ Some one delete the log file.<br>NoneType<br>Stack (most recent call last):<br>File “C:&#x2F;Users&#x2F;wader&#x2F;PycharmProjects&#x2F;LearnPython&#x2F;day06&#x2F;log.py”, line 45, in <module><br>logging.warning(“Some one delete the log file.”, exc_info&#x3D;True, stack_info&#x3D;True, extra&#x3D;<br>{‘user’: ‘Tom’, ‘ip’:’47.98.53.222’})</li>
</ol>
<h4 id="logging模块日志流处理流程"><a href="#logging模块日志流处理流程" class="headerlink" title="logging模块日志流处理流程"></a>logging模块日志流处理流程</h4><p>在介绍logging模块的高级用法之前，很有必要对logging模块所包含的重要组件以及其工作流程做个全面、简要的介<br>绍，这有助于我们更好的理解我们所写的代码（将会触发什么样的操作）。</p>
<h5 id="logging日志模块四大组件"><a href="#logging日志模块四大组件" class="headerlink" title="logging日志模块四大组件"></a>logging日志模块四大组件</h5><p>在介绍logging模块的日志流处理流程之前，我们先来介绍下logging模块的四大组件：<br>Alt text<br>logging模块就是通过这些组件来完成日志处理的，上面所使用的logging模块级别的函数也是通过这些组件对应的类来<br>实现的。<br>这些组件之间的关系描述：<br>•日志器（logger）需要通过处理器（handler）将日志信息输出到目标位置，如：文件、sys.stdout、网络等；<br>•不同的处理器（handler）可以将日志输出到不同的位置；<br>•日志器（logger）可以设置多个处理器（handler）将同一条日志记录输出到不同的位置；<br>•每个处理器（handler）都可以设置自己的过滤器（filter）实现日志过滤，从而只保留感兴趣的日志；<br>•每个处理器（handler）都可以设置自己的格式器（formatter）实现同一条日志以不同的格式输出到不同的地方。<br>简单点说就是：日志器（logger）是入口，真正干活儿的是处理器（handler），处理器（handler）还可以通过过滤器<br>（filter）和格式器（formatter）对要输出的日志内容做过滤和格式化等处理操作。</p>
<h5 id="logging日志模块相关类及其常用方法介绍"><a href="#logging日志模块相关类及其常用方法介绍" class="headerlink" title="logging日志模块相关类及其常用方法介绍"></a>logging日志模块相关类及其常用方法介绍</h5><p>下面介绍下与logging四大组件相关的类：Logger, Handler, Filter, Formatter。<br>Logger类<br>Logger对象有3个任务要做：<br>•1）向应用程序代码暴露几个方法，使应用程序可以在运行时记录日志消息；<br>•2）基于日志严重等级（默认的过滤设施）或filter对象来决定要对哪些日志进行后续处理；<br>•3）将日志消息传送给所有感兴趣的日志handlers。<br>Logger对象最常用的方法分为两类：配置方法 和 消息发送方法<br>最常用的配置方法如下：<br>Alt text<br>关于Logger.setLevel()方法的说明：<br>内建等级中，级别最低的是DEBUG，级别最高的是CRITICAL。例如setLevel(logging.INFO)，此时函数参数为INFO，那<br>么该logger将只会处理INFO、WARNING、ERROR和CRITICAL级别的日志，而DEBUG级别的消息将会被忽略&#x2F;丢弃。<br>logger对象配置完成后，可以使用下面的方法来创建日志记录：<br>Alt text<br>那么，怎样得到一个Logger对象呢？一种方式是通过Logger类的实例化方法创建一个Logger类的实例，但是我们通常都<br>是用第二种方式–logging.getLogger()方法。<br>logging.getLogger()方法有一个可选参数name，该参数表示将要返回的日志器的名称标识，如果不提供该参数，则其<br>值为’root’。若以相同的name参数值多次调用getLogger()方法，将会返回指向同一个logger对象的引用。<br>关于logger的层级结构与有效等级的说明：<br>•logger的名称是一个以’.’分割的层级结构，每个’.’后面的logger都是’.’前面的logger的children，例如，有一个名称为</p>
<p>foo 的logger，其它名称分别为 foo.bar, foo.bar.baz 和 foo.bam都是 foo 的后代。<br>•logger有一个”有效等级（effective level）”的概念。如果一个logger上没有被明确设置一个level，那么该logger就是<br>使用它parent的level;如果它的parent也没有明确设置level则继续向上查找parent的parent的有效level，依次类推，直<br>到找到个一个明确设置了level的祖先为止。需要说明的是，root logger总是会有一个明确的level设置（默认为<br>WARNING）。当决定是否去处理一个已发生的事件时，logger的有效等级将会被用来决定是否将该事件传递给该logger<br>的handlers进行处理。<br>•child loggers在完成对日志消息的处理后，默认会将日志消息传递给与它们的祖先loggers相关的handlers。因此，我<br>们不必为一个应用程序中所使用的所有loggers定义和配置handlers，只需要为一个顶层的logger配置handlers，然后按<br>照需要创建child loggers就可足够了。我们也可以通过将一个logger的propagate属性设置为False来关闭这种传递机<br>制。<br>Handler类<br>Handler对象的作用是（基于日志消息的level）将消息分发到handler指定的位置（文件、网络、邮件等）。Logger对象<br>可以通过addHandler()方法为自己添加0个或者更多个handler对象。比如，一个应用程序可能想要实现以下几个日志需<br>求：<br>•1）把所有日志都发送到一个日志文件中；<br>•2）把所有严重级别大于等于error的日志发送到stdout（标准输出）；<br>•3）把所有严重级别为critical的日志发送到一个email邮件地址。<br>这种场景就需要3个不同的handlers，每个handler复杂发送一个特定严重级别的日志到一个特定的位置。<br>一个handler中只有非常少数的方法是需要应用开发人员去关心的。对于使用内建handler对象的应用开发人员来说，似<br>乎唯一相关的handler方法就是下面这几个配置方法：<br>Alt text<br>需要说明的是，应用程序代码不应该直接实例化和使用Handler实例。因为Handler是一个基类，它只定义了素有<br>handlers都应该有的接口，同时提供了一些子类可以直接使用或覆盖的默认行为。下面是一些常用的Handler：<br>Alt text<br>Formater类<br>Formater对象用于配置日志信息的最终顺序、结构和内容。与logging.Handler基类不同的是，应用代码可以直接实例<br>化Formatter类。另外，如果你的应用程序需要一些特殊的处理行为，也可以实现一个Formatter的子类来完成。<br>Formatter类的构造方法定义如下：<br>logging.Formatter.<strong>init</strong>(fmt&#x3D;None, datefmt&#x3D;None, style&#x3D;’%’)<br>可见，该构造方法接收3个可选参数：<br>•fmt：指定消息格式化字符串，如果不指定该参数则默认使用message的原始值<br>•datefmt：指定日期格式字符串，如果不指定该参数则默认使用”%Y-%m-%d %H:%M:%S”<br>•style：Python 3.2新增的参数，可取值为 ‘%’, ‘{‘和 ‘$’，如果不指定该参数则默认使用’%’<br>Filter类<br>Filter可以被Handler和Logger用来做比level更细粒度的、更复杂的过滤功能。Filter是一个过滤器基类，它只允许某个<br>logger层级下的日志事件通过过滤。该类定义如下：<br>class logging.Filter(name&#x3D;’’)<br>filter(record)<br>比如，一个filter实例化时传递的name参数值为’A.B’，那么该filter实例将只允许名称为类似如下规则的loggers产生的日<br>志记录通过过滤：’A.B’，’A.B,C’，’A.B.C.D’，’A.B.D’，而名称为’A.BB’, ‘B.A.B’的loggers产生的日志则会被过滤掉。</p>
<p>如果name的值为空字符串，则允许所有的日志事件通过过滤。<br>filter方法用于具体控制传递的record记录是否能通过过滤，如果该方法返回值为0表示不能通过过滤，返回值为非0表示<br>可以通过过滤。<br>说明：<br>•如果有需要，也可以在filter(record)方法内部改变该record，比如添加、删除或修改一些属性。<br>•我们还可以通过filter做一些统计工作，比如可以计算下被一个特殊的logger或handler所处理的record数量等。</p>
<h5 id="logging日志流处理流程"><a href="#logging日志流处理流程" class="headerlink" title="logging日志流处理流程"></a>logging日志流处理流程</h5><p>Alt text<br>我们来描述下上面这个图的日志流处理流程：<br>•1）（在用户代码中进行）日志记录函数调用，如：logger.info(…)，logger.debug(…)等；<br>•2）判断要记录的日志级别是否满足日志器设置的级别要求（要记录的日志级别要大于或等于日志器设置的级别才算满<br>足要求），如果不满足则该日志记录会被丢弃并终止后续的操作，如果满足则继续下一步操作；<br>•3）根据日志记录函数调用时掺入的参数，创建一个日志记录（LogRecord类）对象；<br>•4）判断日志记录器上设置的过滤器是否拒绝这条日志记录，如果日志记录器上的某个过滤器拒绝，则该日志记录会被<br>丢弃并终止后续的操作，如果日志记录器上设置的过滤器不拒绝这条日志记录或者日志记录器上没有设置过滤器则继续下<br>一步操作–将日志记录分别交给该日志器上添加的各个处理器；<br>•5）判断要记录的日志级别是否满足处理器设置的级别要求（要记录的日志级别要大于或等于该处理器设置的日志级别<br>才算满足要求），如果不满足记录将会被该处理器丢弃并终止后续的操作，如果满足则继续下一步操作；<br>•6）判断该处理器上设置的过滤器是否拒绝这条日志记录，如果该处理器上的某个过滤器拒绝，则该日志记录会被当前<br>处理器丢弃并终止后续的操作，如果当前处理器上设置的过滤器不拒绝这条日志记录或当前处理器上没有设置过滤器测继<br>续下一步操作；<br>•7）如果能到这一步，说明这条日志记录经过了层层关卡允许被输出了，此时当前处理器会根据自身被设置的格式器<br>（如果没有设置则使用默认格式）将这条日志记录进行格式化，最后将格式化后的结果输出到指定位置（文件、网络、类<br>文件的Stream等）；<br>•8）如果日志器被设置了多个处理器的话，上面的第5-8步会执行多次；<br>•9）这里才是完整流程的最后一步：判断该日志器输出的日志消息是否需要传递给上一级logger（之前提到过，日志器<br>是有层级关系的）的处理器，如果propagate属性值为1则表示日志消息将会被输出到处理器指定的位置，同时还会被传<br>递给parent日志器的handlers进行处理直到当前日志器的propagate属性为0停止，如果propagate值为0则表示不向<br>parent日志器的handlers传递该消息，到此结束。<br>可见，一条日志信息要想被最终输出需要依次经过以下几次过滤：<br>•日志器等级过滤；<br>•日志器的过滤器过滤；<br>•日志器的处理器等级过滤；<br>•日志器的处理器的过滤器过滤；<br>需要说明的是： 关于上面第9个步骤，如果propagate值为1，那么日志消息会直接传递交给上一级logger的handlers进<br>行处理，此时上一级logger的日志等级并不会对该日志消息进行等级过滤。</p>
<h4 id="使用logging四大组件记录日志"><a href="#使用logging四大组件记录日志" class="headerlink" title="使用logging四大组件记录日志"></a>使用logging四大组件记录日志</h4><p>现在，我们对logging模块的重要组件及整个日志流处理流程都应该有了一个比较全面的了解，下面我们来看一个例子。</p>
<h5 id="需求"><a href="#需求" class="headerlink" title="需求"></a>需求</h5><p>现在有以下几个日志记录的需求：<br>•1）要求将所有级别的所有日志都写入磁盘文件中</p>
<p>•2）all.log文件中记录所有的日志信息，日志格式为：日期和时间 - 日志级别 - 日志信息<br>•3）error.log文件中单独记录error及以上级别的日志信息，日志格式为：日期和时间 - 日志级别 - 文件名[:行号] - 日<br>志信息<br>•4）要求all.log在每天凌晨进行日志切割</p>
<h5 id="分析"><a href="#分析" class="headerlink" title="分析"></a>分析</h5><p>•1）要记录所有级别的日志，因此日志器的有效level需要设置为最低级别–DEBUG;<br>•2）日志需要被发送到两个不同的目的地，因此需要为日志器设置两个handler；另外，两个目的地都是磁盘文件，因此<br>这两个handler都是与FileHandler相关的；<br>•3）all.log要求按照时间进行日志切割，因此他需要用logging.handlers.TimedRotatingFileHandler; 而error.log没<br>有要求日志切割，因此可以使用FileHandler;<br>•4）两个日志文件的格式不同，因此需要对这两个handler分别设置格式器；</p>
<h5 id="代码实现"><a href="#代码实现" class="headerlink" title="代码实现"></a>代码实现</h5><p>import logging<br>import logging.handlers<br>import datetime<br>logger &#x3D; logging.getLogger(‘mylogger’)<br>logger.setLevel(logging.DEBUG)<br>rf_handler &#x3D; logging.handlers.TimedRotatingFileHandler(‘all.log’, when&#x3D;’midnight’,<br>interval&#x3D;1, backupCount&#x3D;7, atTime&#x3D;datetime.time(0, 0, 0, 0))<br>rf_handler.setFormatter(logging.Formatter(“%(asctime)s ‐ %(levelname)s ‐ %(message)s”))<br>f_handler &#x3D; logging.FileHandler(‘error.log’)<br>f_handler.setLevel(logging.ERROR)<br>f_handler.setFormatter(logging.Formatter(“%(asctime)s ‐ %(levelname)s ‐ %(filename)s[:%<br>(lineno)d] ‐ %(message)s”))<br>logger.addHandler(rf_handler)<br>logger.addHandler(f_handler)<br>logger.debug(‘debug message’)<br>logger.info(‘info message’)<br>logger.warning(‘warning message’)<br>logger.error(‘error message’)<br>logger.critical(‘critical message’)<br>all.log文件输出<br>2017‐05‐13<br>2017‐05‐13<br>2017‐05‐13<br>2017‐05‐13<br>2017‐05‐13</p>
<p>16:12:40,612<br>16:12:40,612<br>16:12:40,612<br>16:12:40,612<br>16:12:40,613</p>
<p>DEBUG ‐ debug message<br>INFO ‐ info message<br>WARNING ‐ warning message<br>ERROR ‐ error message<br>CRITICAL ‐ critical message</p>
<p>error.log文件输出<br>2017‐05‐13 16:12:40,612 ‐ ERROR ‐ log.py[:81] ‐ error message<br>2017‐05‐13 16:12:40,613 ‐ CRITICAL ‐ log.py[:82] ‐ critical message</p>
<h2 id="python自动化打开音乐下载网站下载音乐脚本例子"><a href="#python自动化打开音乐下载网站下载音乐脚本例子" class="headerlink" title="python自动化打开音乐下载网站下载音乐脚本例子"></a>python自动化打开音乐下载网站下载音乐脚本例子</h2><p>使用的是python中色selenium包，selenium2.0接入了webdriver的api</p>
<p>webdriver需要先安装相应浏览器的驱动放到浏览器和python的安装位置（chrome、safari、ie、fox）</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">#coding=utf-8</span><br><span class="line">from selenium import webdriver</span><br><span class="line">from selenium.webdriver.common.keys import Keys</span><br><span class="line">import time</span><br><span class="line"></span><br><span class="line">chrome_obj = webdriver.Chrome()</span><br><span class="line">#chrome_obj.maximize_window()</span><br><span class="line"></span><br><span class="line">chrometitle = chrome_obj.title</span><br><span class="line">print(chrometitle)</span><br><span class="line"></span><br><span class="line">chrome_obj.get(&quot;https://music.sounm.com/yinyue/&quot;)</span><br><span class="line">chrome_obj.find_element_by_xpath(&#x27;//div[@class=&quot;btn-box&quot;]&#x27;).click()</span><br><span class="line">chrome_obj.find_element(&#x27;id&#x27;,&#x27;search-wd&#x27;).send_keys(&#x27;不要说话&#x27;)</span><br><span class="line">chrome_obj.find_element_by_xpath(&#x27;//input[@value=&quot;netease&quot;]&#x27;).send_keys(Keys.SPACE)</span><br><span class="line">chrome_obj.find_element_by_xpath(&#x27;//button[@class=&quot;search-submit&quot;]&#x27;).submit()</span><br><span class="line">time.sleep(100)</span><br><span class="line">chrome_obj.close()</span><br></pre></td></tr></table></figure>

<p>其中使用两种寻找方式，find_element_by_id根据id查找，还是根据相对路径find_element_by_xpath；导入keys包，发送space按键；导入time包，停止100秒</p>
<h2 id="WSGI框架"><a href="#WSGI框架" class="headerlink" title="WSGI框架"></a>WSGI框架</h2><p>python WSGI框架详解<br>1.web应用的本质<br>1)浏览器发送一个HTTP请求<br>2)服务器收到请求，生成一个HTML文档<br>3)服务器把HTML文档作为HTTP响应的body发个浏览器<br>4)浏览器收到HTTP响应，从HTTP Body取出HTML文档并显示</p>
<p>2.什么是WSGI,为什么需要WSGI<br>上面的web应用过程，如果由我们自己来实现是复杂的，接收HTTP请求，解析HTTP请求，响应HTTP请求等。<br>通常这些操作都由WSGI服务器来完成，WSGI（Web Server Gateway Interface）定义了WSGI服务器执行的接口，我们只需要编写服务WSGI规范的接口，然后由WSGI服务器来执行，就可以了。</p>
<p>3.WSGI接口编写示例</p>
<p>def application(environ,satrt_response):<br>    start_response(‘200 OK’,[(‘Content-Type’,’text&#x2F;html’)])<br>    return ‘<h1>Hello,web!</h1>‘<br>上面的application()函数就是符合WSGI标准的一个HTTP处理函数<br>参数说明：<br>environ：包含HTTP请求信息的dict对象<br>satrt_response:发送HTTP响应的函数<br>函数说明：<br>start_response(‘200 OK’, [(‘Content-Type’, ‘text&#x2F;html’)])<br>发送HTTP响应的Header，Header只能发送一次，意思是start_response函数只能执行一次<br>‘200 OK’是HTTP响应码参数，[(‘Content-Type’, ‘text&#x2F;html’)]表示HTTP Header</p>
<p>函数的返回值return ‘<h1>Hello,web!</h1>‘作为HTTP响应body发送给服务器。</p>
<p>接收HTTP请求，解析HTTP请求，发送HTTP请求等操作就交由WSGI服务器去完成，WSGI接口只负责业务逻辑。</p>
<p>4.python WSGI服务器<br>python内置了一个WSGI服务器，这个模块叫做wsgiref，不过这个模块没有考虑运行效率，只是为了开发和测试使用。</p>
<p>5.python编写运行WSGI web应用示例<br>1)编写WSGI接口</p>
<p>def application(environ,satrt_response):<br>    start_response(‘200 OK’,[(‘Content-Type’,’text&#x2F;html’)])<br>    return ‘<h1>Hello,web!</h1>‘<br>2)编写server.py，启动初始化WSGI服务器，加载application()函数</p>
<p>复制代码</p>
<h1 id="server-py"><a href="#server-py" class="headerlink" title="server.py"></a>server.py</h1><h1 id="从wsgiref模块导入"><a href="#从wsgiref模块导入" class="headerlink" title="从wsgiref模块导入:"></a>从wsgiref模块导入:</h1><p>from wsgiref.simple_server import make_server</p>
<h1 id="导入我们自己编写的application函数"><a href="#导入我们自己编写的application函数" class="headerlink" title="导入我们自己编写的application函数:"></a>导入我们自己编写的application函数:</h1><p>from hello import application</p>
<h1 id="创建一个服务器，IP地址为空，端口是8000，处理函数是application"><a href="#创建一个服务器，IP地址为空，端口是8000，处理函数是application" class="headerlink" title="创建一个服务器，IP地址为空，端口是8000，处理函数是application:"></a>创建一个服务器，IP地址为空，端口是8000，处理函数是application:</h1><p>httpd &#x3D; make_server(‘’, 8000, application)<br>print “Serving HTTP on port 8000…”</p>
<h1 id="开始监听HTTP请求"><a href="#开始监听HTTP请求" class="headerlink" title="开始监听HTTP请求:"></a>开始监听HTTP请求:</h1><p>httpd.serve_forever()<br>复制代码<br>运行：python server.py<br>打开浏览器，输入<a target="_blank" rel="noopener" href="http://localhost:8000/%EF%BC%8C%E5%B0%B1%E5%8F%AF%E4%BB%A5%E7%9C%8B%E5%88%B0%E7%BB%93%E6%9E%9C%E4%BA%86%E3%80%82">http://localhost:8000/，就可以看到结果了。</a></p>
<hr>
<hr>
<p>wsgi全称Web Server Gateway Interface，是一个规范，定义web服务器如何与python应用程序进行交互。</p>
<p>wsgi的目的有两个：<br>1、让Web服务器知道如何调用Python应用程序，并且把用户的请求告诉应用程序。<br>2、让Python应用程序知道用户的具体请求是什么，以及如何返回结果给Web服务器。</p>
<p>在WSGI中定义了两个角色，Web服务器端称为server或者gateway，应用程序端称为application或者framework。</p>
<p>server端会先收到用户的请求，然后会根据规范的要求调用application端，如下所示：</p>
<p><strong>SERVER&#x2F;GATEWAY—————-APPLICATION&#x2F;FRAMEWORK</strong></p>
<p>调用的结果会被封装成HTTP响应后再发送给客户端。</p>
<p>#server如何调用application<br>首先，每个application的入口只有一个，也就是所有的客户端请求都同一个入口进入到应用程序。</p>
<blockquote>
<p>这个application就是root</p>
</blockquote>
<p>接下来，server端需要知道去哪里找application的入口。这个需要在server端指定一个Python模块，也就是Python应用中的一个文件，并且这个模块中需要包含一个名称为application的可调用对象（函数和类都可以），这个application对象就是这个应用程序的唯一入口了。WSGI还定义了application对象的形式：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">def simple_app(environ, start_response):</span><br><span class="line">      pass</span><br></pre></td></tr></table></figure>
<p>所有支持WSGI的python框架都有一个application的对象。框架的使用者不需要关心application是怎么工作的，只需要关心路由定义、请求处理等具体的业务逻辑。</p>
<p>#application对象需要做什么<br>当server调用application了之后，application就开始处理请求了，请求处理之后，application需要返回处理结果给server。<strong>处理请求</strong>和<strong>返回结果</strong>这两个动作都和environ、start_response参数有关。</p>
<p>##environ参数<br>environ参数是一个Python的字典，里面存放了所有和客户端相关的信息，这样application对象就能知道客户端请求的资源是什么，请求中带了什么数据等。environ字典包含了一些CGI规范要求的数据，以及WSGI规范新增的数据，还可能包含一些操作系统的环境变量以及Web服务器相关的环境变量。我们来看一些environ中常用的成员：</p>
<p>首先是CGI规范中要求的变量：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">REQUEST_METHOD： 请求方法，是个字符串，&#x27;GET&#x27;, &#x27;POST&#x27;等</span><br><span class="line">SCRIPT_NAME： HTTP请求的path中的用于查找到application对象的部分，比如Web服务器可以根据path的一部分来决定请求由哪个virtual host处理</span><br><span class="line">PATH_INFO： HTTP请求的path中剩余的部分，也就是application要处理的部分</span><br><span class="line">QUERY_STRING： HTTP请求中的查询字符串，URL中?后面的内容</span><br><span class="line">CONTENT_TYPE： HTTP headers中的content-type内容</span><br><span class="line">CONTENT_LENGTH： HTTP headers中的content-length内容</span><br><span class="line">SERVER_NAME和SERVER_PORT： 服务器名和端口，这两个值和前面的SCRIPT_NAME, PATH_INFO拼起来可以得到完整的URL路径</span><br><span class="line">SERVER_PROTOCOL： HTTP协议版本，HTTP/1.0或者HTTP/1.1</span><br><span class="line">HTTP_： 和HTTP请求中的headers对应。</span><br><span class="line">WSGI规范中还要求environ包含下列成员：</span><br><span class="line"></span><br><span class="line">wsgi.version：表示WSGI版本，一个元组(1, 0)，表示版本1.0</span><br><span class="line">wsgi.url_scheme：http或者https</span><br><span class="line">wsgi.input：一个类文件的输入流，application可以通过这个获取HTTP request body</span><br><span class="line">wsgi.errors：一个输出流，当应用程序出错时，可以将错误信息写入这里</span><br><span class="line">wsgi.multithread：当application对象可能被多个线程同时调用时，这个值需要为True</span><br><span class="line">wsgi.multiprocess：当application对象可能被多个进程同时调用时，这个值需要为True</span><br><span class="line">wsgi.run_once：当server期望application对象在进程的生命周期内只被调用一次时，该值为True</span><br></pre></td></tr></table></figure>

<p>上面列出的这些内容已经包括了客户端请求的所有数据，足够application对象处理客户端请求了。</p>
<h2 id="start-resposne参数"><a href="#start-resposne参数" class="headerlink" title="start_resposne参数"></a>start_resposne参数</h2><p>start_response是一个可调用对象，接收两个必选参数和一个可选参数：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">status: 一个字符串，表示HTTP响应状态字符串</span><br><span class="line">response_headers: 一个列表，包含有如下形式的元组：(header_name, header_value)，用来表示HTTP响应的headers</span><br><span class="line">exc_info（可选）: 用于出错时，server需要返回给浏览器的信息</span><br></pre></td></tr></table></figure>

<p>当application对象根据environ参数的内容执行完业务逻辑后，就需要返回结果给server端。我们知道HTTP的响应需要包含status，headers和body，所以在application对象将body作为返回值return之前，需要先调用start_response()，将status和headers的内容返回给server，这同时也是告诉server，application对象要开始返回body了。</p>
<p>#application对象的返回值</p>
<p>application对象的返回值用于为HTTP响应提供body，如果没有body，那么可以返回None。如果有body的化，那么需要返回一个可迭代的对象。server端通过遍历这个可迭代对象可以获得body的全部内容。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">def simple_app(environ, start_response):</span><br><span class="line">      status = &#x27;200 OK&#x27;</span><br><span class="line">      response_headers = [(&#x27;Content-type&#x27;, &#x27;text/plain&#x27;)]</span><br><span class="line">      start_response(status, response_headers)</span><br><span class="line">      return [&#x27;hello, world&#x27;]</span><br></pre></td></tr></table></figure>

<p>app.py 一般包含了Pecan应用的入口，包含应用初始化代码<br>config.py 包含Pecan的应用配置，会被app.py使用<br>controllers&#x2F; 这个目录会包含所有的控制器，也就是API具体逻辑的地方<br>controllers&#x2F;root.py 这个包含根路径对应的控制器<br>controllers&#x2F;v1&#x2F; 这个目录对应v1版本的API的控制器。如果有多个版本的API，你一般能看到v2等目录。</p>
<h1 id="WSGI网关协议理解"><a href="#WSGI网关协议理解" class="headerlink" title="WSGI网关协议理解"></a>WSGI网关协议理解</h1><p><strong>网关协议</strong>是一个链接浏览器与服务器端的框架协议</p>
<p>B端发送request请求到服务器，服务器针对请求在路径文件夹内返回html文件给浏览器展示。</p>
<p>对于静态请求可以用nginx作为server，可以处理高并发。</p>
<p>对于动态请求可以用apache作为server，处理这些动态请求需要编写专门的动态application来处理数据返回给server。</p>
<p><strong>问题：</strong></p>
<ul>
<li>需要花费大量的精力去处理server与application之间的通讯和传输。</li>
<li>如果换一个server，例如apache换成nginx，则applicaiton所写的接口全都不能用.</li>
<li>一种动态请求处理函数只针对一种情况，对于每种情况都写请求函数则存在大量的代码复用。</li>
</ul>
<p><strong>解决：</strong></p>
<ul>
<li>使用一个web app开发框架，基于网关协议标准实现。则不管server或者app怎么变换改动都遵循同一个网关标准。</li>
<li>CGI网关协议标准     FastCGI     </li>
<li>WSGI网关协议标准一开始是专门开发出来解决python后端同server接驳的框架，有了这个标准就不用考虑server是怎么运行的，只要application符合这个标准接口去开发，则可以移植到任何支持WSGI的server端。</li>
<li>keystone就是一个python开源的基于WSGI接口标准的application</li>
</ul>
<h3 id="WSGI中间件"><a href="#WSGI中间件" class="headerlink" title="WSGI中间件"></a><strong>WSGI中间件</strong></h3><p>WSGI中间件就是处于application和server之间的middleware。有点像nginx的正向代理&#x2F;反向代理。中间件对于application是server，对于服务器是应用程序。中间件可以做一些缓存的功能，同时降低了server与app的耦合。</p>
<p><em><font size=2>正向代理：把nginx作为客户端去访问server，需要客户端设置代理服务器的ip、port等。</font></em></p>
<p><em><font size=2>反向代理：把nginx作为server端接收Browser的请求，并根据设置把请求分发到真正的服务器，对于客户端来说，nginx 就是一个server。</font></em></p>
<p>WSGI: web server（WSGI server） – middleware – WSGI application</p>
<ul>
<li>建立socket，监听端口，等待request</li>
<li>解析信息，放到环境变量environ中，调用绑定的handler处理请求</li>
<li>handler解析请求，将method、path放入environ中</li>
<li>handler将一些服务器端信息也放入environ中</li>
<li>WSGI handler调用WSGI application ，将environ和回调函数传给WSGI app</li>
<li>app将response包含head&#x2F;body&#x2F;status等传给handler</li>
<li>handler 通过socke传给客户端</li>
</ul>
<p>所以从以上过程路我们知道application接受两个参数：<strong>environ</strong>和<strong>start_response</strong>。</p>
<h3 id="WSGI三个特征"><a href="#WSGI三个特征" class="headerlink" title="WSGI三个特征"></a>WSGI三个特征</h3><ol>
<li><p>是一个可调用的对象</p>
<p>WSGI的可调用对象的形式有函数、类、类的实例</p>
<table>
<thead>
<tr>
<th align="center">形式</th>
<th align="center">说明</th>
</tr>
</thead>
<tbody><tr>
<td align="center">函数</td>
<td align="center">WSGI application直接调用，函数里参数有environ、start_response这两个参数</td>
</tr>
<tr>
<td align="center">类的实例</td>
<td align="center">类必须有__call__函数，参数是environ、response，web server会调用__call__函数</td>
</tr>
<tr>
<td align="center">类</td>
<td align="center">类必须有__call__函数，参数是environ、response，web server会创建这个类实例，调用实例的__call__函数</td>
</tr>
</tbody></table>
</li>
<li><p>包含environ和start_response两个参数</p>
<p>web server调用这个可调入对象时会传入两个参数</p>
<ul>
<li><p>environ：CGI相关的环境变量、操作系统相关的环境变量（非必须）、WSGI相关的环境变量、服务器自定义的环境变量（非必须）</p>
</li>
<li><p>start_response：是web server传递给WSGI application的一个callable object。有点绕，从server看，WSGI application本身就是一个callable object，再给它传递一个callable object，start_response表现形式是一个函数</p>
<p>start_response(status, response_header, exc_info&#x3D;None) </p>
<p>status是状态码。response_header是列表，形式是（header_name, header_value）。exc_info是错误处理</p>
</li>
</ul>
</li>
<li><p>有一个可迭代的返回值</p>
<p>example：</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">def</span> <span class="title function_">my_app</span>(<span class="params">environ start_respones</span>):</span><br><span class="line">    <span class="keyword">if</span>(今天股票大涨):</span><br><span class="line">        <span class="keyword">return</span> your_app(environ, start_response)</span><br><span class="line">    <span class="keyword">else</span>:</span><br><span class="line">        start_response(<span class="string">&quot;200 ok&quot;</span>, [(<span class="string">&quot;Content-Type&quot;</span>,<span class="string">&quot;text/heml&quot;</span>)])</span><br><span class="line">        <span class="keyword">return</span> <span class="string">&#x27;hello,stock&#x27;</span></span><br></pre></td></tr></table></figure>

<p>两种回复值，如果它web server收到else响应，那么它就以这个返回值响应它的client的请求；如果收到if响应，则调用Your_app继续迭代下去。</p>
</li>
</ol>

        </div>

        
            <section class="post-copyright">
                
                    <p class="copyright-item">
                        <span>Author:</span>
                        <span>Ian Tang</span>
                    </p>
                
                
                    <p class="copyright-item">
                        <span>Permalink:</span>
                        <span><a href="https://tkhfree.github.io/2022/11/27/python%E6%A6%82%E8%BF%B0%E5%92%8C%E6%80%BB%E7%BB%93-2022-11-27/">https://tkhfree.github.io/2022/11/27/python%E6%A6%82%E8%BF%B0%E5%92%8C%E6%80%BB%E7%BB%93-2022-11-27/</a></span>
                    </p>
                
                
                    <p class="copyright-item">
                        <span>License:</span>
                        <span>Copyright (c) 2019 <a target="_blank" rel="noopener" href="http://creativecommons.org/licenses/by-nc/4.0/">CC-BY-NC-4.0</a> LICENSE</span>
                    </p>
                
                
                     <p class="copyright-item">
                         <span>Slogan:</span>
                         <span>Do you believe in <strong>DESTINY</strong>?</span>
                     </p>
                

            </section>
        
        <section class="post-tags">
            <div>
                <span>Tag(s):</span>
                <span class="tag">
                    
                    
                        <a href="/tags/python/"># python</a>
                    
                        
                </span>
            </div>
            <div>
                <a href="javascript:window.history.back();">back</a>
                <span>· </span>
                <a href="/">home</a>
            </div>
        </section>
        <section class="post-nav">
            
                <a class="prev" rel="prev" href="/2022/11/27/Vscode%E7%BC%96%E8%BE%91C%E9%A1%B9%E7%9B%AE-2022-11-27/">Vscode编辑C项目</a>
            
            
            <a class="next" rel="next" href="/2022/11/27/python%E5%8C%85%E7%9A%84%E5%87%A0%E7%A7%8D%E7%AE%A1%E7%90%86%E5%B7%A5%E5%85%B7-2022-11-27/">python包的几种管理工具</a>
            
        </section>


    </article>
</div>

            </div>
            <footer id="footer" class="footer">
    <div class="copyright">
        <span>© Ian Tang | Powered by <a href="https://hexo.io" target="_blank">Hexo</a> & <a href="https://github.com/Siricee/hexo-theme-Chic" target="_blank">Chic</a></span>
    </div>
</footer>

    </div>
</body>

</html>